#ifndef APPLICATION_H
#define APPLICATION_H

#include "MouseCursor.h"
#include "ScreenWriter.h"
#include "Picker.h"
#include "PrimitiveFactory.h"
#include "FirstPersonCameraController.h"

#include <OgreRoot.h>
#include <OgreRenderWindow.h>
#include <OgreSceneManager.h>
#include <OgreCamera.h>
#include <OgreWindowEventUtilities.h>

#include <OIS.h>

#include <OgreNewt.h>
#include <OgreNewt_BasicFrameListener.h>

class Application : public OIS::MouseListener, public OIS::KeyListener, public Ogre::WindowEventListener
{
public:
	Application();
	~Application();

	bool initialise();
	bool setup();
	void run();

	bool mouseMoved(const OIS::MouseEvent &evt);
	bool mousePressed(const OIS::MouseEvent &evt, OIS::MouseButtonID);
	bool mouseReleased(const OIS::MouseEvent &evt, OIS::MouseButtonID);
	
	bool keyPressed(const OIS::KeyEvent &evt);
	bool keyReleased(const OIS::KeyEvent &evt);

	void windowMoved(Ogre::RenderWindow* rw) {};
	void windowFocusChange(Ogre::RenderWindow* rw) {};
	void windowResized(Ogre::RenderWindow* rw);
	void windowClosed(Ogre::RenderWindow* rw);

private:
	Ogre::Root* ogre;
	Ogre::RenderWindow* window;
	Ogre::SceneManager* sceneManager;
	Ogre::Camera* camera;
	Ogre::Viewport* viewport;

	OIS::InputManager* ois;
	OIS::Mouse* mouse;
	OIS::Keyboard* keyboard;

	MouseCursor* cursor;
	ScreenWriter* debug;
	Picker* picker;
	PrimitiveFactory* factory;
	FirstPersonCameraController* firstPersonCameraController;

	OgreNewt::World* world;
	OgreNewt::MaterialPair* defaultMaterialPair;

	OgreNewt::Hinge* spinnerHinge;

	int desiredPhysicsFramerate;
	int lastFPS;

	unsigned long lastFrameTime;
	unsigned long lastFrameDuration;

	Ogre::Real physicsTimeAccumulator;
	Ogre::Real physicsUpdateStep;

	bool running;
	bool debuggerActive;
};

#endif